home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 16
/
Aminet 16 (1996)(GTI - Schatztruhe)[!][Dec 1996].iso
/
Aminet
/
comm
/
term
/
term_extras.lha
/
Extras
/
HydraCom
/
hydracom-source.lha
/
amiga.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-10-11
|
52KB
|
2,503 lines
/*
** :ts=4
**
** Amiga support module for HYDRA protocol sample implementation.
**
** Written by Olaf Barthel
** Brabeckstrasse 35
** D-30559 Hannover
**
** eMail: olsen@sourcery.han.de
**
** Freely distributable.
*/
/* System includes. */
#include <intuition/intuitionbase.h>
#include <libraries/gadtools.h>
#include <libraries/locale.h>
#include <libraries/asl.h>
#include <graphics/gfxbase.h>
#include <utility/date.h>
#include <devices/conunit.h>
#include <devices/serial.h>
#include <devices/timer.h>
#include <hardware/cia.h>
#include <dos/dosextens.h>
#include <dos/filehandler.h>
#include <dos/dostags.h>
#include <dos/dosasl.h>
#include <exec/memory.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/graphics_protos.h>
#include <clib/utility_protos.h>
#include <clib/locale_protos.h>
#include <clib/timer_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/asl_protos.h>
#include <clib/macros.h>
#include <pragmas/intuition_pragmas.h>
#include <pragmas/gadtools_pragmas.h>
#include <pragmas/graphics_pragmas.h>
#include <pragmas/utility_pragmas.h>
#include <pragmas/locale_pragmas.h>
#include <pragmas/timer_pragmas.h>
#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/asl_pragmas.h>
#include <errno.h>
//#define DB(x) x
#define DB(x) ;
void __stdargs kprintf(STRPTR,...);
#include "Rendezvous.h"
#include "hydracom.h"
/* Difference between UTC and Amiga time. */
#define UTC_OFFSET 252482400
/* Minimum of lines to reserve for local input. */
#define MIN_LINES 3
/* Serial buffer size. */
#define BUFFER_SIZE 8192
/* Maximum length of a file name for now. */
#define MAX_FILENAME_LENGTH 256
/* A handy macro. */
#define ClrSignal(s) SetSignal(0,s)
/* this macro lets us long-align structures on the stack */
#define D_S(type,name) char a_##name[sizeof(type)+3]; \
type *name = (type *)((LONG)(a_##name+3) & ~3);
/* Signal masks. */
#define SIG_SERREAD (1UL << ReadPort->mp_SigBit)
#define SIG_SERWRITE (1UL << WritePort->mp_SigBit)
#define SIG_CONREAD (1UL << ConsoleReadPort->mp_SigBit)
#define SIG_TIMER (1UL << TimePort->mp_SigBit)
#define SIG_WINDOW (1UL << WindowPort->mp_SigBit)
#define SIG_HANDSHAKE SIGF_SINGLE
#define SIG_KILL SIGBREAKF_CTRL_C
/* A serial buffer structure. */
struct SerialBuffer
{
struct IOExtSer *SerialRequest;
UBYTE *SerialBuffer,
*SerialIndex,
*SerialTop;
LONG SerialSize,
SerialFilled;
BOOL IsClone,
IsBusy;
};
/* Special rendezvous data. */
STATIC struct RendezvousData *RendezvousData;
STATIC struct RendezvousSemaphore *RendezvousSemaphore;
/* Library bases. */
extern struct ExecBase *SysBase;
extern struct DosLibrary *DOSBase;
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct LocaleBase *LocaleBase;
struct Library *GadToolsBase,
*UtilityBase,
*TimerBase,
*AslBase;
/* Timer data. */
struct MsgPort *TimePort;
struct timerequest *TimeRequest;
/* Serial data. */
struct MsgPort *ReadPort,
*WritePort;
struct SerialBuffer *ThisBuffer,
*NextBuffer,
*ReadBuffer;
/* Console data. */
struct MsgPort *WindowPort;
struct Window *FileWindow,
*RemoteWindow,
*LocalWindow,
*LogWindow;
struct MsgPort *ConsoleWritePort,
*ConsoleReadPort;
struct IOStdReq *ConsoleReadRequest;
UBYTE ConsoleChar;
BOOL ConsoleReady = FALSE,
WindowReady = FALSE;
struct IOStdReq *FileRequest,
*RemoteRequest,
*LocalRequest,
*LogRequest;
/* DOS Data. */
struct Process *ThisProcess;
APTR OldPtr;
LONG OldPri;
struct AnchorPath *Anchor;
BOOL AnchorUsed = FALSE;
/* Screen data. */
struct Screen *PublicScreen,
*Screen;
/* Menu data. */
APTR VisualInfo;
struct Menu *Menu;
struct NewMenu MenuTemplate[] =
{
{ NM_TITLE, "Project", 0 , 0, 0, (APTR)0},
{ NM_ITEM, "Toggle chat", "C", 0, 0, (APTR)Alt_C},
{ NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0},
{ NM_ITEM, "Hang up", "H", 0, 0, (APTR)Alt_H},
{ NM_ITEM, "Toggle duplex", "E", 0, 0, (APTR)Alt_E},
{ NM_ITEM, "Toggle 7 bits/8 bits", "B", 0, 0, (APTR)Alt_B},
{ NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0},
{ NM_ITEM, "Start upload", "U", 0, 0, (APTR)PgUp},
{ NM_ITEM, "Start download", "D", 0, 0, (APTR)PgDn},
{ NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0},
{ NM_ITEM, "Abort Hydra session", ".", 0, 0, (APTR)Esc},
{ NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0},
{ NM_ITEM, "Exit HydraCom", "Q", 0, 0, (APTR)Alt_X},
{ NM_END }
};
/* Time data. */
LONG GMT_Offset = UTC_OFFSET;
/* Standard file requester. */
struct FileRequester *FileRequester;
/* Version ID. */
STRPTR VersionTag = "$VER: hydracom 1.0r7 (15.12.95)\r\n";
/* CloseWindowSafely(struct Window *Window):
*
* Close a window sharing its UserPort with other
* windows.
*/
STATIC VOID
CloseWindowSafely(struct Window *Window)
{
Forbid();
if(Window->UserPort)
{
struct Node *Node,*Next;
for(Node = Window->UserPort->mp_MsgList.lh_Head ; Next = Node->ln_Succ ; Node = Next)
{
if(((struct IntuiMessage *)Node)->IDCMPWindow == Window)
{
Remove(Node);
ReplyMsg((struct Message *)Node);
}
}
Window->UserPort = NULL;
}
ModifyIDCMP(Window,NULL);
Permit();
CloseWindow(Window);
}
/* UpdateTime(struct timeval *Now):
*
* Get the current time and/or update the current
* time offset data.
*/
STATIC VOID
UpdateTime(struct timeval *Now)
{
if(Now)
Now->tv_secs = Now->tv_micro = 0;
if(TimePort = CreateMsgPort())
{
if(TimeRequest = (struct timerequest *)CreateIORequest(TimePort,sizeof(struct timerequest)))
{
if(!OpenDevice(TIMERNAME,UNIT_VBLANK,TimeRequest,NULL))
{
TimerBase = (struct Library *)TimeRequest->tr_node.io_Device;
if(LocaleBase = (struct LocaleBase *)OpenLibrary("locale.library",38))
{
struct Locale *Locale = OpenLocale(NULL);
GMT_Offset = 60 * Locale->loc_GMTOffset + UTC_OFFSET;
CloseLocale(Locale);
CloseLibrary(LocaleBase);
LocaleBase = NULL;
}
if(Now)
GetSysTime(Now);
TimerBase = NULL;
CloseDevice(TimeRequest);
}
DeleteIORequest(TimeRequest);
TimeRequest = NULL;
}
DeleteMsgPort(TimePort);
TimePort = NULL;
}
}
STATIC VOID
AddString(STRPTR Buffer,LONG MaxLen,STRPTR NewString)
{
LONG i,Len,BufferLen;
BOOL HasSpace;
Len = strlen(NewString);
BufferLen = strlen(Buffer);
HasSpace = FALSE;
for(i = 0 ; i < Len ; i++)
{
if(NewString[i] == ' ')
{
HasSpace = TRUE;
Len += 2;
break;
}
}
Len++;
if(BufferLen + Len < MaxLen)
{
if(HasSpace)
sprintf(&Buffer[BufferLen],"\"%s\" ",NewString);
else
sprintf(&Buffer[BufferLen],"%s ",NewString);
}
}
/* GetFiles(char *Buffer,int MaxLen):
*
* Get a list of file names.
*/
char *
GetFiles(char *Buffer,int MaxLen)
{
if(AslRequestTags(FileRequester,
ASLFR_Window, LocalWindow,
ASLFR_SleepWindow, TRUE,
TAG_DONE))
{
if(FileRequester->fr_NumArgs > 0)
{
UBYTE LocalBuffer[MAX_FILENAME_LENGTH];
LONG Len,Count,i;
for(i = Count = 0 ; i < FileRequester->fr_NumArgs ; i++)
{
if(FileRequester->fr_ArgList[i].wa_Lock)
{
if(!NameFromLock(FileRequester->fr_ArgList[i].wa_Lock,LocalBuffer,sizeof(LocalBuffer)))
{
Count = -1;
break;
}
}
else
{
Len = strlen(FileRequester->fr_Drawer);
if(Len >= sizeof(LocalBuffer))
{
Count = -1;
break;
}
else
strcpy(LocalBuffer,FileRequester->fr_Drawer);
}
if(AddPart(LocalBuffer,FileRequester->fr_ArgList[i].wa_Name,sizeof(LocalBuffer)))
{
LONG j;
Len = strlen(LocalBuffer) + 1;
for(j = 0 ; j < Len ; j++)
{
if(j == ' ')
{
Len += 2;
break;
}
}
if(Len < sizeof(LocalBuffer))
{
if(Count + Len < MaxLen)
Count += Len;
else
{
Count = -1;
break;
}
}
}
}
if(Count > 0)
{
Buffer[0] = 0;
for(i = 0 ; i < FileRequester->fr_NumArgs ; i++)
{
if(FileRequester->fr_ArgList[i].wa_Lock)
{
if(!NameFromLock(FileRequester->fr_ArgList[i].wa_Lock,LocalBuffer,sizeof(LocalBuffer)))
break;
}
else
{
Len = strlen(FileRequester->fr_Drawer);
if(Len >= sizeof(LocalBuffer))
break;
else
strcpy(LocalBuffer,FileRequester->fr_Drawer);
}
if(AddPart(LocalBuffer,FileRequester->fr_ArgList[i].wa_Name,sizeof(LocalBuffer)))
AddString(Buffer,MaxLen,LocalBuffer);
}
return(Buffer);
}
}
else
{
if(FileRequester->fr_File[0])
{
LONG Len;
Len = strlen(FileRequester->fr_Drawer) + strlen(FileRequester->fr_File) + 2 + 2;
if(Len <= MaxLen)
{
strcpy(Buffer,FileRequester->fr_Drawer);
AddPart(Buffer,FileRequester->fr_File,MaxLen);
return(Buffer);
}
}
}
}
return(NULL);
}
/* OpenConsole():
*
* Open a console window.
*/
STATIC BOOL
OpenConsole(struct Screen *Screen,LONG Top,LONG Height,STRPTR Title,BOOL Resize,struct Window **WindowPtr,struct IOStdReq **ConsolePtr)
{
struct Window *Window;
if(Window = OpenWindowTags(NULL,
WA_Left, 0,
WA_Top, Top,
WA_Width, Screen->Width,
WA_Height, Height,
WA_Title, Title,
WA_SimpleRefresh, TRUE,
WA_DepthGadget, TRUE,
WA_DragBar, TRUE,
WA_SizeGadget, Resize,
WA_SizeBRight, TRUE,
WA_CustomScreen, Screen,
WA_NewLookMenus, TRUE,
TAG_DONE))
{
Window->UserPort = WindowPort;
SetMenuStrip(Window,Menu);
if(ModifyIDCMP(Window,IDCMP_MENUPICK))
{
struct IOStdReq *ConsoleRequest;
if(Window->RPort->Font->tf_Flags & FPF_PROPORTIONAL)
SetFont(Window->RPort,GfxBase->DefaultFont);
if(ConsoleRequest = (struct IOStdReq *)CreateIORequest(ConsoleWritePort,sizeof(struct IOStdReq)))
{
ConsoleRequest->io_Data = Window;
if(!OpenDevice("console.device",CONU_CHARMAP,ConsoleRequest,CONFLAG_DEFAULT))
{
WindowLimits(Window,Window->BorderLeft + 10 * Window->RPort->Font->tf_XSize * 10 + Window->BorderRight,Window->BorderTop + 2 * Window->RPort->Font->tf_YSize + Window->BorderBottom,Screen->Width,Screen->Height);
/* Turn off the cursor. */
ConPrintf(ConsoleRequest,"\033[0 p");
*WindowPtr = Window;
*ConsolePtr = ConsoleRequest;
return(TRUE);
}
DeleteIORequest(ConsoleRequest);
}
}
ClearMenuStrip(Window);
CloseWindowSafely(Window);
}
return(FALSE);
}
/* CloseConsole():
*
* Close a console window.
*/
STATIC VOID
CloseConsole(struct Window **WindowPtr,struct IOStdReq **ConsolePtr)
{
if(*ConsolePtr)
{
CloseDevice(*ConsolePtr);
DeleteIORequest(*ConsolePtr);
*ConsolePtr = NULL;
}
if(*WindowPtr)
{
ClearMenuStrip(*WindowPtr);
CloseWindowSafely(*WindowPtr);
*WindowPtr = NULL;
}
}
/* CloneSerialBuffer():
*
* Clone a SerialBuffer structure.
*/
STATIC struct SerialBuffer *
CloneSerialBuffer(struct SerialBuffer *Source,struct MsgPort *MsgPort)
{
struct SerialBuffer *Buffer;
if(Buffer = (struct SerialBuffer *)AllocVec(sizeof(struct SerialBuffer) + Source->SerialSize,MEMF_ANY | MEMF_PUBLIC))
{
Buffer->SerialBuffer = Buffer->SerialIndex = (UBYTE *)(Buffer + 1);
Buffer->SerialFilled = 0;
Buffer->SerialTop = Buffer->SerialBuffer + Source->SerialSize;
Buffer->SerialSize = Source->SerialSize;
Buffer->IsClone = TRUE;
Buffer->IsBusy = FALSE;
if(Buffer->SerialRequest = (struct IOExtSer *)AllocVec(sizeof(struct IOExtSer),MEMF_ANY | MEMF_PUBLIC))
{
CopyMem(Source->SerialRequest,Buffer->SerialRequest,sizeof(struct IOExtSer));
Buffer->SerialRequest->IOSer.io_Message.mn_ReplyPort = MsgPort;
return(Buffer);
}
else
cprint("Could not create serial request\n");
FreeVec(Buffer);
}
else
cprint("Could not create serial buffer\n");
return(NULL);
}
/* DeleteSerialBuffer():
*
* Delete a SerialBuffer structure.
*/
STATIC VOID
DeleteSerialBuffer(struct SerialBuffer *Buffer)
{
if(Buffer)
{
if(Buffer->IsBusy)
{
if(!CheckIO(Buffer->SerialRequest))
AbortIO(Buffer->SerialRequest);
WaitIO(Buffer->SerialRequest);
}
if(Buffer->IsClone)
FreeVec(Buffer->SerialRequest);
else
{
CloseDevice(Buffer->SerialRequest);
DeleteIORequest(Buffer->SerialRequest);
}
FreeVec(Buffer);
}
}
/* CreateSerialBuffer():
*
* Create a serial buffer structure.
*/
STATIC struct SerialBuffer *
CreateSerialBuffer(STRPTR Device,LONG Unit,LONG Size,struct MsgPort *MsgPort)
{
struct SerialBuffer *Buffer;
if(Buffer = (struct SerialBuffer *)AllocVec(sizeof(struct SerialBuffer) + Size,MEMF_ANY | MEMF_PUBLIC))
{
Buffer->SerialBuffer = Buffer->SerialIndex = (UBYTE *)(Buffer + 1);
Buffer->SerialFilled = 0;
Buffer->SerialTop = Buffer->SerialBuffer + Size;
Buffer->SerialSize = Size;
Buffer->IsClone = FALSE;
Buffer->IsBusy = FALSE;
if(Buffer->SerialRequest = (struct IOExtSer *)CreateIORequest(MsgPort,sizeof(struct IOExtSer)))
{
Buffer->SerialRequest->io_SerFlags = SERF_SHARED|SERF_7WIRE;
if(!OpenDevice(Device,Unit,Buffer->SerialRequest,NULL))
return(Buffer);
else
{
cprint("Could not open \"%s\", unit %d\n",Device,Unit);
DeleteIORequest(Buffer->SerialRequest);
}
}
else
cprint("Could not create serial request\n");
FreeVec(Buffer);
}
else
cprint("Could not create serial buffer\n");
return(NULL);
}
/* OpenAll():
*
* Allocate all the resources required.
*/
STATIC BOOL
OpenAll(STRPTR Device,LONG Unit)
{
LONG Top,Lines,BorderSize,FontSize,ExtraLines,RemainingLines,TotalHeight;
UWORD Pens = (UWORD)~0;
ThisProcess = (struct Process *)FindTask(NULL);
if(pri != 1000)
{
if(pri < -128)
pri = 128;
else
{
if(pri > 127)
pri = 127;
}
OldPri = SetTaskPri(ThisProcess,pri);
}
if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37)))
{
cprint("Could not open intuition.library v37\n");
return(FALSE);
}
if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",37)))
{
cprint("Could not open graphics.library v37\n");
return(FALSE);
}
if(!(GadToolsBase = OpenLibrary("gadtools.library",37)))
{
cprint("Could not open gadtools.library v37\n");
return(FALSE);
}
if(!(UtilityBase = OpenLibrary("utility.library",37)))
{
cprint("Could not open utility.library v37\n");
return(FALSE);
}
if(!(AslBase = OpenLibrary("asl.library",37)))
{
cprint("Could not open asl.library v37\n");
return(FALSE);
}
if(!(FileRequester = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest,
ASLFR_TitleText, "Select file(s) to upload",
ASLFR_InitialPattern, "#?",
ASLFR_Flags1, FRF_PRIVATEIDCMP | FRF_DOMULTISELECT | FRF_DOPATTERNS,
TAG_DONE)))
{
cprint("Could not allocate file requester.\n");
return(FALSE);
}
if(LocaleBase = (struct LocaleBase *)OpenLibrary("locale.library",38))
{
struct Locale *Locale;
if(Locale = OpenLocale(NULL))
{
GMT_Offset = 60 * Locale->loc_GMTOffset + UTC_OFFSET;
CloseLocale(Locale);
}
CloseLibrary(LocaleBase);
}
if(!(TimePort = CreateMsgPort()))
{
cprint("Could not create timer port\n");
return(FALSE);
}
if(!(TimeRequest = (struct timerequest *)CreateIORequest(TimePort,sizeof(struct timerequest))))
{
cprint("Could not create timer request\n");
return(FALSE);
}
if(OpenDevice(TIMERNAME,UNIT_VBLANK,TimeRequest,NULL))
{
cprint("Could not open timer\n");
return(FALSE);
}
TimerBase = (struct Library *)TimeRequest->tr_node.io_Device;
if(!(Anchor = (struct AnchorPath *)AllocVec(sizeof(struct AnchorPath) + 512,MEMF_ANY | MEMF_CLEAR)))
{
cprint("Could not allocate pattern matching buffe\n");
return(FALSE);
}
Anchor->ap_Strlen = 512;
if(!(ReadPort = CreateMsgPort()))
{
cprint("Could not create serial read port\n");
return(FALSE);
}
if(!(WritePort = CreateMsgPort()))
{
cprint("Could not create serial write port\n");
return(FALSE);
}
Forbid();
if(RendezvousSemaphore = (struct RendezvousSemaphore *)FindSemaphore(Device))
{
ObtainSemaphore(RendezvousSemaphore);
if(!(RendezvousData = (*RendezvousSemaphore->rs_Login)(ReadPort,WritePort,NULL)))
{
Permit();
ReleaseSemaphore(RendezvousSemaphore);
RendezvousSemaphore = NULL;
cprint("Could not link to `term' port \"%s\"\n",Device);
return(FALSE);
}
}
Permit();
if(!(ConsoleReadPort = CreateMsgPort()))
{
cprint("Could not create console read port\n");
return(FALSE);
}
if(!(ConsoleWritePort = CreateMsgPort()))
{
cprint("Could not create console write port\n");
return(FALSE);
}
if(!(ConsoleReadRequest = (struct IOStdReq *)AllocVec(sizeof(struct IOStdReq),MEMF_ANY | MEMF_PUBLIC | MEMF_CLEAR)))
{
cprint("Could not create console read request\n");
return(FALSE);
}
if(!RendezvousData)
{
if(!(ReadBuffer = CreateSerialBuffer(Device,Unit,BUFFER_SIZE,ReadPort)))
return(FALSE);
}
else
{
if(ReadBuffer = (struct SerialBuffer *)AllocVec(sizeof(struct SerialBuffer) + BUFFER_SIZE,MEMF_ANY | MEMF_PUBLIC))
{
ReadBuffer->SerialBuffer = ReadBuffer->SerialIndex = (UBYTE *)(ReadBuffer + 1);
ReadBuffer->SerialFilled = 0;
ReadBuffer->SerialTop = ReadBuffer->SerialBuffer + BUFFER_SIZE;
ReadBuffer->SerialSize = BUFFER_SIZE;
ReadBuffer->IsClone = TRUE;
ReadBuffer->IsBusy = FALSE;
ReadBuffer->SerialRequest = &RendezvousData->rd_ReadRequest;
/* Ralph Seichter suggested reusing the data
* stored in the rendezvous data.
*/
com_speed = ReadBuffer->SerialRequest->io_Baud;
if(cur_speed > com_speed)
cur_speed = com_speed;
if(ReadBuffer->SerialRequest->io_ReadLen == 7 && ReadBuffer->SerialRequest->io_WriteLen == 7 && (ReadBuffer->SerialRequest->io_SerFlags & (SERF_PARTY_ON|SERF_PARTY_ODD)) == SERF_PARTY_ON && !(ReadBuffer->SerialRequest->io_SerFlags & (SEXTF_MSPON|SEXTF_MARK)))
{
parity = true;
hydra_options |= HOPT_HIGHBIT;
}
else
parity = false;
}
else
{
cprint("Could not create serial ReadBuffer\n");
return(FALSE);
}
}
if(!(ThisBuffer = CloneSerialBuffer(ReadBuffer,WritePort)))
return(FALSE);
if(!(NextBuffer = CloneSerialBuffer(ReadBuffer,WritePort)))
return(FALSE);
if(!(PublicScreen = LockPubScreen(NULL)))
{
cprint("Could not find default public screen\n");
return(FALSE);
}
if(RendezvousData)
{
if(!(Screen = RendezvousData->rd_Screen))
Screen = PublicScreen;
}
else
{
if(!(Screen = OpenScreenTags(NULL,
SA_DisplayID, GetVPModeID(&PublicScreen->ViewPort),
SA_Overscan, OSCAN_TEXT,
SA_Depth, 2,
SA_Title, PRGNAME " " VERSION " " HC_OS " Amiga rev 8, ported by Olaf `Olsen' Barthel",
SA_Behind, TRUE,
SA_SysFont, 1,
SA_Pens, &Pens,
SA_Interleaved, TRUE,
TAG_DONE)))
{
cprint("Could not open screen\n");
return(FALSE);
}
}
if(!(VisualInfo = GetVisualInfo(Screen,TAG_DONE)))
{
cprint("Could not obtain screen visual info\n");
return(FALSE);
}
if(!(Menu = CreateMenus(MenuTemplate,TAG_DONE)))
{
cprint("Could not create menus\n");
return(FALSE);
}
if(!LayoutMenus(Menu,VisualInfo,
GTMN_TextAttr, Screen->Font,
GTMN_NewLookMenus, TRUE,
TAG_DONE))
{
cprint("Could not layout menus\n");
return(FALSE);
}
Top = Screen->BarHeight + 1;
BorderSize = Screen->WBorTop + Screen->Font->ta_YSize + 1 + Screen->WBorBottom;
FontSize = GfxBase->DefaultFont->tf_YSize;
TotalHeight = Screen->Height - Top;
Lines = (TotalHeight - 3 - 4 * BorderSize) / FontSize;
ExtraLines = Lines > MIN_LINES ? (Lines - MIN_LINES) / 3 : 0;
RemainingLines = Lines > MIN_LINES + ExtraLines * 3 ? Lines - (MIN_LINES + ExtraLines * 3) : 0;
if(Lines < MIN_LINES)
{
cprint("Screen size too small (need at least %d text lines, can get only %d)\n",MIN_LINES,Lines);
return(FALSE);
}
if(!(WindowPort = CreateMsgPort()))
{
cprint("Could not create window port\n");
return(FALSE);
}
if(!OpenConsole(Screen,Top,BorderSize + (6 + ExtraLines) * FontSize,"Log",TRUE,&LogWindow,&LogRequest))
{
cprint("Could not open console window #1\n");
return(FALSE);
}
TotalHeight -= LogWindow->Height + 1;
Top += LogWindow->Height + 1;
if(!OpenConsole(Screen,Top,BorderSize + 2 * FontSize,"File",FALSE,&FileWindow,&FileRequest))
{
cprint("Could not open console window #2\n");
return(FALSE);
}
ConPrintf(FileRequest,"\033[?7l");
TotalHeight -= FileWindow->Height + 1;
Top += FileWindow->Height + 1;
if(!OpenConsole(Screen,Top,BorderSize + (8 + RemainingLines) * FontSize,"Remote",TRUE,&RemoteWindow,&RemoteRequest))
{
cprint("Could not open console window #3\n");
return(FALSE);
}
TotalHeight -= RemoteWindow->Height + 1;
Top += RemoteWindow->Height + 1;
if(!OpenConsole(Screen,Top,TotalHeight,"Local (Press [Amiga+C] to start/end chat mode, [Esc] to abort Hydra session)",TRUE,&LocalWindow,&LocalRequest))
{
cprint("Could not open console window #4\n");
return(FALSE);
}
CopyMem(LocalRequest,ConsoleReadRequest,sizeof(struct IOStdReq));
ConsoleReadRequest->io_Message.mn_ReplyPort = ConsoleReadPort;
/* Turn the cursors back on. */
ConPrintf(LocalRequest,"\33[ p");
ConPrintf(RemoteRequest,"\33[ p");
ConsoleReadRequest->io_Command = CMD_READ;
ConsoleReadRequest->io_Data = &ConsoleChar;
ConsoleReadRequest->io_Length = 1;
ClrSignal(SIG_CONREAD);
SendIO(ConsoleReadRequest);
OldPtr = ThisProcess->pr_WindowPtr;
ThisProcess->pr_WindowPtr = (APTR)LocalWindow;
if(!quiet)
{
ScreenToFront(Screen);
ActivateWindow(LocalWindow);
}
UnlockPubScreen(NULL,PublicScreen);
PublicScreen = NULL;
if(!RendezvousData)
com_flow(flowflags);
return(TRUE);
}
/* CloseAll():
*
* Close all the resources.
*/
STATIC VOID
CloseAll(VOID)
{
if(FileRequester)
FreeAslRequest(FileRequester);
if(LocalWindow)
ClearMenuStrip(LocalWindow);
if(Menu)
FreeMenus(Menu);
if(VisualInfo)
FreeVisualInfo(VisualInfo);
if(AnchorUsed)
MatchEnd(Anchor);
if(Anchor)
FreeVec(Anchor);
if(ThisProcess)
ThisProcess->pr_WindowPtr = OldPtr;
if(ConsoleReadRequest)
{
if(ConsoleReadRequest->io_Device)
{
if(!CheckIO(ConsoleReadRequest))
AbortIO(ConsoleReadRequest);
WaitIO(ConsoleReadRequest);
}
FreeVec(ConsoleReadRequest);
}
CloseConsole(&LocalWindow,&LocalRequest);
CloseConsole(&RemoteWindow,&RemoteRequest);
CloseConsole(&FileWindow,&FileRequest);
CloseConsole(&LogWindow,&LogRequest);
if(WindowPort)
DeleteMsgPort(WindowPort);
if(!RendezvousData && Screen)
CloseScreen(Screen);
if(PublicScreen)
UnlockPubScreen(NULL,PublicScreen);
DeleteSerialBuffer(NextBuffer);
DeleteSerialBuffer(ThisBuffer);
if(RendezvousData)
{
if(ReadBuffer->IsBusy)
{
if(!CheckIO(ReadBuffer->SerialRequest))
AbortIO(ReadBuffer->SerialRequest);
WaitIO(ReadBuffer->SerialRequest);
}
FreeVec(ReadBuffer);
}
else
DeleteSerialBuffer(ReadBuffer);
if(ConsoleWritePort)
DeleteMsgPort(ConsoleWritePort);
if(ConsoleReadPort)
DeleteMsgPort(ConsoleReadPort);
if(WritePort)
DeleteMsgPort(WritePort);
if(ReadPort)
DeleteMsgPort(ReadPort);
if(TimeRequest)
{
if(TimeRequest->tr_node.io_Device)
CloseDevice(TimeRequest);
DeleteIORequest(TimeRequest);
}
if(TimePort)
DeleteMsgPort(TimePort);
if(UtilityBase)
CloseLibrary(UtilityBase);
if(AslBase)
CloseLibrary(AslBase);
if(GadToolsBase)
CloseLibrary(GadToolsBase);
if(GfxBase)
CloseLibrary(GfxBase);
if(IntuitionBase)
CloseLibrary(IntuitionBase);
if(RendezvousData)
{
(*RendezvousSemaphore->rs_Logoff)(RendezvousData);
RendezvousData = NULL;
}
if(RendezvousSemaphore)
{
ReleaseSemaphore(RendezvousSemaphore);
RendezvousSemaphore = NULL;
}
if(pri != 1000)
OldPri = SetTaskPri(ThisProcess,OldPri);
}
/* ConPutc():
*
* Output a single character.
*/
VOID __stdargs
ConPutc(struct IOStdReq *Request,UBYTE Char)
{
Request->io_Command = CMD_WRITE;
Request->io_Data = &Char;
Request->io_Length = 1;
DoIO(Request);
}
/* ConPuts():
*
* Output a string.
*/
VOID
ConPuts(struct IOStdReq *Request,STRPTR String)
{
Request->io_Command = CMD_WRITE;
Request->io_Data = String;
Request->io_Length = strlen(String);
DoIO(Request);
}
/* ConPrintf():
*
* Formatted console output.
*/
VOID __stdargs
ConPrintf(struct IOStdReq *Request,STRPTR Format,...)
{
STATIC UBYTE Buffer[512];
va_list VarArgs;
LONG Len;
va_start(VarArgs,Format);
vsprintf(Buffer,Format,VarArgs);
va_end(VarArgs);
Len = strlen(Buffer);
if(Buffer[0] != '\033' && Request == FileRequest)
{
struct ConUnit *Unit = (struct ConUnit *)Request->io_Unit;
if(Unit->cu_XCCP + Len > Unit->cu_XMax)
{
if((Len = Unit->cu_XMax - Unit->cu_XCCP) < 1)
return;
}
}
Request->io_Command = CMD_WRITE;
Request->io_Data = Buffer;
Request->io_Length = Len;
DoIO(Request);
}
/* ConMove():
*
* Move the cursor to a new position.
*/
VOID
ConMove(struct IOStdReq *Request,LONG x,LONG y)
{
ConPrintf(Request,"\33[%ld;%ldH",y,x);
}
/* ConClear():
*
* Clear the console window.
*/
VOID
ConClear(struct IOStdReq *Request)
{
struct ConUnit *ConUnit = (struct ConUnit *)Request->io_Device;
LONG x,y;
x = ConUnit->cu_XCCP;
y = ConUnit->cu_YCCP;
ConPrintf(Request,"\033[2J\33[%ld;%ldH",y,x);
}
/* ConGetKey():
*
* Read a character from a console window.
*/
int
ConGetKey()
{
if(ConsoleReady)
{
int Result = ConsoleChar;
ConsoleReady = FALSE;
ConsoleReadRequest->io_Command = CMD_READ;
ConsoleReadRequest->io_Data = &ConsoleChar;
ConsoleReadRequest->io_Length = 1;
ClrSignal(SIG_CONREAD);
SendIO(ConsoleReadRequest);
return(Result);
}
else
{
int Result = 0;
if(WindowReady)
{
struct IntuiMessage *IntuiMessage;
ULONG MsgClass;
UWORD MsgCode;
while(IntuiMessage = (struct IntuiMessage *)GetMsg(LocalWindow->UserPort))
{
MsgClass = IntuiMessage->Class;
MsgCode = IntuiMessage->Code;
ReplyMsg(IntuiMessage);
if(MsgClass == IDCMP_MENUPICK)
{
struct MenuItem *Item;
while(MsgCode != MENUNULL)
{
if(Item = ItemAddress(Menu,MsgCode))
{
if(MENU_USERDATA(Item))
{
if(!Result)
Result = (int)MENU_USERDATA(Item);
}
MsgCode = Item->NextSelect;
}
else
break;
}
}
}
WindowReady = FALSE;
}
return(Result);
}
}
/* ConScanKey():
*
* Check for a keyboard event.
*/
int
ConScanKey()
{
if(ConsoleReady || WindowReady)
return(1);
else
{
int Result = 0;
if(CheckSignal(SIG_WINDOW))
{
WindowReady = TRUE;
Result = 1;
}
if(CheckIO(ConsoleReadRequest))
{
if(!WaitIO(ConsoleReadRequest))
{
ConsoleReady = TRUE;
return(1);
}
else
{
ConsoleReadRequest->io_Command = CMD_READ;
ConsoleReadRequest->io_Data = &ConsoleChar;
ConsoleReadRequest->io_Length = 1;
ClrSignal(SIG_CONREAD);
SendIO(ConsoleReadRequest);
}
}
return(Result);
}
return(0);
}
/* dtr_out(byte flag):
*
* If flag == 0->drop DTR signal, else set it.
*/
VOID
dtr_out(byte flag)
{
if(!flag && !RendezvousData)
{
if(ThisBuffer->IsBusy)
{
WaitIO(ThisBuffer->SerialRequest);
ThisBuffer->IsBusy = FALSE;
ThisBuffer->SerialIndex = ThisBuffer->SerialBuffer;
}
if(ReadBuffer->IsBusy)
{
if(!CheckIO(ReadBuffer->SerialRequest))
AbortIO(ReadBuffer->SerialRequest);
WaitIO(ReadBuffer->SerialRequest);
ReadBuffer->IsBusy = FALSE;
ReadBuffer->SerialFilled = ReadBuffer->SerialRequest->IOSer.io_Actual;
ReadBuffer->SerialIndex = ReadBuffer->SerialBuffer;
ReadBuffer->SerialRequest->IOSer.io_Command = SDCMD_QUERY;
DoIO(ReadBuffer->SerialRequest);
if(ReadBuffer->SerialRequest->IOSer.io_Actual)
{
LONG Size = ReadBuffer->SerialSize - ReadBuffer->SerialFilled;
if(Size > 0)
{
if(Size > ReadBuffer->SerialRequest->IOSer.io_Actual)
Size = ReadBuffer->SerialRequest->IOSer.io_Actual;
ReadBuffer->SerialRequest->IOSer.io_Command = CMD_READ;
ReadBuffer->SerialRequest->IOSer.io_Data = ReadBuffer->SerialBuffer + ReadBuffer->SerialFilled;
ReadBuffer->SerialRequest->IOSer.io_Length = Size;
DoIO(ReadBuffer->SerialRequest);
ReadBuffer->SerialFilled += ReadBuffer->SerialRequest->IOSer.io_Actual;
}
}
}
CloseDevice(ReadBuffer->SerialRequest);
TimeRequest->tr_node.io_Command = TR_ADDREQUEST;
TimeRequest->tr_time.tv_secs = 1;
TimeRequest->tr_time.tv_micro = 0;
DoIO(TimeRequest);
if(OpenDevice(device,port,ReadBuffer->SerialRequest,NULL))
{
CloseAll();
exit(10);
}
else
{
ReadBuffer->SerialRequest->io_Baud = ThisBuffer->SerialRequest->io_Baud;
ReadBuffer->SerialRequest->io_ReadLen = ThisBuffer->SerialRequest->io_ReadLen;
ReadBuffer->SerialRequest->io_WriteLen = ThisBuffer->SerialRequest->io_WriteLen;
ReadBuffer->SerialRequest->io_SerFlags = ThisBuffer->SerialRequest->io_SerFlags;
ReadBuffer->SerialRequest->IOSer.io_Command = SDCMD_SETPARAMS;
DoIO(ReadBuffer->SerialRequest);
CopyMem(ReadBuffer->SerialRequest,ThisBuffer->SerialRequest,sizeof(struct IOExtSer));
ThisBuffer->SerialRequest->IOSer.io_Message.mn_ReplyPort = WritePort;
CopyMem(ReadBuffer->SerialRequest,NextBuffer->SerialRequest,sizeof(struct IOExtSer));
NextBuffer->SerialRequest->IOSer.io_Message.mn_ReplyPort = WritePort;
}
}
}
/* com_flow(byte flags):
*
* The bit mask `flags' determines the style(s) of
* handshaking:
*
* if (flags & 9)->enable xON/xOFF software handshaking,
* if (flags & 2)->enable RTS/CTS hardware handshaking
*/
VOID
com_flow(byte flags)
{
if(ThisBuffer->IsBusy)
{
WaitIO(ThisBuffer->SerialRequest);
ThisBuffer->IsBusy = FALSE;
ThisBuffer->SerialIndex = ThisBuffer->SerialBuffer;
}
if(ReadBuffer->IsBusy)
{
if(!CheckIO(ReadBuffer->SerialRequest))
AbortIO(ReadBuffer->SerialRequest);
WaitIO(ReadBuffer->SerialRequest);
ReadBuffer->IsBusy = FALSE;
ReadBuffer->SerialFilled = ReadBuffer->SerialRequest->IOSer.io_Actual;
ReadBuffer->SerialIndex = ReadBuffer->SerialBuffer;
ReadBuffer->SerialRequest->IOSer.io_Command = SDCMD_QUERY;
DoIO(ReadBuffer->SerialRequest);
if(ReadBuffer->SerialRequest->IOSer.io_Actual)
{
LONG Size = ReadBuffer->SerialSize - ReadBuffer->SerialFilled;
if(Size > 0)
{
if(Size > ReadBuffer->SerialRequest->IOSer.io_Actual)
Size = ReadBuffer->SerialRequest->IOSer.io_Actual;
ReadBuffer->SerialRequest->IOSer.io_Command = CMD_READ;
ReadBuffer->SerialRequest->IOSer.io_Data = ReadBuffer->SerialBuffer + ReadBuffer->SerialFilled;
ReadBuffer->SerialRequest->IOSer.io_Length = Size;
DoIO(ReadBuffer->SerialRequest);
ReadBuffer->SerialFilled += ReadBuffer->SerialRequest->IOSer.io_Actual;
}
}
}
if(flags & 2)
ReadBuffer->SerialRequest->io_SerFlags |= SERF_7WIRE;
else
ReadBuffer->SerialRequest->io_SerFlags &= ~SERF_7WIRE;
if(flags & 9)
ReadBuffer->SerialRequest->io_SerFlags &= ~SERF_XDISABLED;
else
ReadBuffer->SerialRequest->io_SerFlags |= SERF_XDISABLED;
ReadBuffer->SerialRequest->IOSer.io_Command = SDCMD_SETPARAMS;
DoIO(ReadBuffer->SerialRequest);
ThisBuffer->SerialRequest->io_SerFlags = ReadBuffer->SerialRequest->io_SerFlags;
NextBuffer->SerialRequest->io_SerFlags = ReadBuffer->SerialRequest->io_SerFlags;
}
/* com_setspeed(word speed):
*
* Set the transfer speed (in bits/second).
*/
VOID
com_setspeed(word speed)
{
if(ThisBuffer->IsBusy)
{
WaitIO(ThisBuffer->SerialRequest);
ThisBuffer->IsBusy = FALSE;
ThisBuffer->SerialIndex = ThisBuffer->SerialBuffer;
}
if(ReadBuffer->IsBusy)
{
if(!CheckIO(ReadBuffer->SerialRequest))
AbortIO(ReadBuffer->SerialRequest);
WaitIO(ReadBuffer->SerialRequest);
ReadBuffer->IsBusy = FALSE;
ReadBuffer->SerialFilled = ReadBuffer->SerialRequest->IOSer.io_Actual;
ReadBuffer->SerialIndex = ReadBuffer->SerialBuffer;
ReadBuffer->SerialRequest->IOSer.io_Command = SDCMD_QUERY;
DoIO(ReadBuffer->SerialRequest);
if(ReadBuffer->SerialRequest->IOSer.io_Actual)
{
LONG Size = ReadBuffer->SerialSize - ReadBuffer->SerialFilled;
if(Size > 0)
{
if(Size > ReadBuffer->SerialRequest->IOSer.io_Actual)
Size = ReadBuffer->SerialRequest->IOSer.io_Actual;
ReadBuffer->SerialRequest->IOSer.io_Command = CMD_READ;
ReadBuffer->SerialRequest->IOSer.io_Data = ReadBuffer->SerialBuffer + ReadBuffer->SerialFilled;
ReadBuffer->SerialRequest->IOSer.io_Length = Size;
DoIO(ReadBuffer->SerialRequest);
ReadBuffer->SerialFilled += ReadBuffer->SerialRequest->IOSer.io_Actual;
}
}
}
ReadBuffer->SerialRequest->io_Baud = speed;
if(parity)
{
ReadBuffer->SerialRequest->io_ReadLen = ReadBuffer->SerialRequest->io_WriteLen = 7;
ReadBuffer->SerialRequest->io_SerFlags |= SERF_PARTY_ON;
}
else
{
ReadBuffer->SerialRequest->io_ReadLen = ReadBuffer->SerialRequest->io_WriteLen = 8;
ReadBuffer->SerialRequest->io_SerFlags &= ~SERF_PARTY_ON;
}
ReadBuffer->SerialRequest->IOSer.io_Command = SDCMD_SETPARAMS;
DoIO(ReadBuffer->SerialRequest);
ThisBuffer->SerialRequest->io_Baud = ReadBuffer->SerialRequest->io_Baud;
ThisBuffer->SerialRequest->io_ReadLen = ReadBuffer->SerialRequest->io_ReadLen;
ThisBuffer->SerialRequest->io_WriteLen = ReadBuffer->SerialRequest->io_WriteLen;
ThisBuffer->SerialRequest->io_SerFlags = ReadBuffer->SerialRequest->io_SerFlags;
NextBuffer->SerialRequest->io_Baud = ReadBuffer->SerialRequest->io_Baud;
NextBuffer->SerialRequest->io_ReadLen = ReadBuffer->SerialRequest->io_ReadLen;
NextBuffer->SerialRequest->io_WriteLen = ReadBuffer->SerialRequest->io_WriteLen;
NextBuffer->SerialRequest->io_SerFlags = ReadBuffer->SerialRequest->io_SerFlags;
}
/* com_putblock(byte *s,word len):
*
* Send a data block asynchronously.
*/
VOID
com_putblock(byte *s,word len)
{
struct SerialBuffer *Swap = ThisBuffer;
if(ThisBuffer->IsBusy)
WaitIO(ThisBuffer->SerialRequest);
else
{
if(ThisBuffer->SerialIndex > ThisBuffer->SerialBuffer)
{
ThisBuffer->SerialRequest->IOSer.io_Command = CMD_WRITE;
ThisBuffer->SerialRequest->IOSer.io_Data = ThisBuffer->SerialBuffer;
ThisBuffer->SerialRequest->IOSer.io_Length = ThisBuffer->SerialIndex - ThisBuffer->SerialBuffer;
DoIO(ThisBuffer->SerialRequest);
}
}
ThisBuffer->IsBusy = FALSE;
ThisBuffer->SerialIndex = ThisBuffer->SerialBuffer;
ThisBuffer = NextBuffer;
NextBuffer = Swap;
if(ThisBuffer->SerialIndex > ThisBuffer->SerialBuffer)
{
ThisBuffer->SerialRequest->IOSer.io_Command = CMD_WRITE;
ThisBuffer->SerialRequest->IOSer.io_Data = ThisBuffer->SerialBuffer;
ThisBuffer->SerialRequest->IOSer.io_Length = ThisBuffer->SerialIndex - ThisBuffer->SerialBuffer;
DoIO(ThisBuffer->SerialRequest);
}
ThisBuffer->IsBusy = FALSE;
ThisBuffer->SerialIndex = ThisBuffer->SerialBuffer;
while(len > 2 * ThisBuffer->SerialSize)
{
ThisBuffer->SerialRequest->IOSer.io_Command = CMD_WRITE;
ThisBuffer->SerialRequest->IOSer.io_Data = s;
ThisBuffer->SerialRequest->IOSer.io_Length = ThisBuffer->SerialSize;
s += ThisBuffer->SerialSize;
len -= ThisBuffer->SerialSize;
DoIO(ThisBuffer->SerialRequest);
}
CopyMem(s,ThisBuffer->SerialBuffer,MIN(len,ThisBuffer->SerialSize));
ThisBuffer->IsBusy = TRUE;
ThisBuffer->SerialIndex = ThisBuffer->SerialBuffer + MIN(len,ThisBuffer->SerialSize);
ThisBuffer->SerialRequest->IOSer.io_Command = CMD_WRITE;
ThisBuffer->SerialRequest->IOSer.io_Data = ThisBuffer->SerialBuffer;
ThisBuffer->SerialRequest->IOSer.io_Length = MIN(len,ThisBuffer->SerialSize);
len -= ThisBuffer->SerialRequest->IOSer.io_Length;
s += ThisBuffer->SerialRequest->IOSer.io_Length;
ClrSignal(SIG_SERWRITE);
SendIO(ThisBuffer->SerialRequest);
if(len > 0)
{
CopyMem(s,NextBuffer->SerialBuffer,len);
NextBuffer->SerialIndex = NextBuffer->SerialBuffer + len;
}
}
/* breakfunc():
*
* Cleanup routine for SAS/C.
*/
static int
breakfunc(void)
{
CloseAll();
return(1);
}
/* sys_init(VOID):
*
* Initialize this driver implementation.
*/
VOID
sys_init(VOID)
{
if(!OpenAll(device,port))
{
CloseAll();
endprog(2);
}
onbreak(breakfunc);
}
/* sys_reset(VOID):
*
* Perform cleanup for this driver implementation.
*/
VOID
sys_reset(VOID)
{
CloseAll();
}
/* sys_idle(VOID):
*
* This routine gets called when the system is idle.
* That's a nice one. We are supposed to call the
* system scheduler, etc.
*/
VOID
sys_idle(VOID)
{
ULONG Signals;
if(ReadBuffer->SerialFilled <= 0 && !ReadBuffer->IsBusy)
{
ReadBuffer->IsBusy = TRUE;
ReadBuffer->SerialIndex = ReadBuffer->SerialBuffer;
ReadBuffer->SerialRequest->IOSer.io_Command = CMD_READ;
ReadBuffer->SerialRequest->IOSer.io_Data = ReadBuffer->SerialBuffer;
ReadBuffer->SerialRequest->IOSer.io_Length = 1;
ClrSignal(SIG_SERREAD);
SendIO(ReadBuffer->SerialRequest);
}
TimeRequest->tr_node.io_Command = TR_ADDREQUEST;
TimeRequest->tr_time.tv_secs = 1;
TimeRequest->tr_time.tv_micro = 0;
ClrSignal(SIG_TIMER);
SendIO(TimeRequest);
Signals = Wait(SIG_SERREAD | SIG_SERWRITE | SIG_CONREAD | SIG_WINDOW | SIG_TIMER);
if(!(Signals & SIG_TIMER))
{
if(!CheckIO(TimeRequest))
AbortIO(TimeRequest);
}
WaitIO(TimeRequest);
if(Signals & SIG_SERREAD)
{
WaitIO(ReadBuffer->SerialRequest);
ReadBuffer->IsBusy = FALSE;
ReadBuffer->SerialFilled = ReadBuffer->SerialRequest->IOSer.io_Actual;
ReadBuffer->SerialIndex = ReadBuffer->SerialBuffer;
ReadBuffer->SerialRequest->IOSer.io_Command = SDCMD_QUERY;
DoIO(ReadBuffer->SerialRequest);
if(ReadBuffer->SerialRequest->IOSer.io_Actual)
{
LONG Size = ReadBuffer->SerialSize - ReadBuffer->SerialFilled;
if(Size > 0)
{
if(Size > ReadBuffer->SerialRequest->IOSer.io_Actual)
Size = ReadBuffer->SerialRequest->IOSer.io_Actual;
ReadBuffer->SerialRequest->IOSer.io_Command = CMD_READ;
ReadBuffer->SerialRequest->IOSer.io_Data = ReadBuffer->SerialBuffer + ReadBuffer->SerialFilled;
ReadBuffer->SerialRequest->IOSer.io_Length = Size;
DoIO(ReadBuffer->SerialRequest);
ReadBuffer->SerialFilled += ReadBuffer->SerialRequest->IOSer.io_Actual;
}
}
}
if(Signals & SIG_SERWRITE)
{
struct SerialBuffer *Swap = ThisBuffer;
WaitIO(ThisBuffer->SerialRequest);
ThisBuffer->IsBusy = FALSE;
ThisBuffer->SerialIndex = ThisBuffer->SerialBuffer;
ThisBuffer = NextBuffer;
NextBuffer = Swap;
}
if(Signals & SIG_CONREAD)
{
WaitIO(ConsoleReadRequest);
ConsoleReady = TRUE;
}
if(Signals & SIG_WINDOW)
WindowReady = TRUE;
}
/* com_outfull(VOID):
*
* Return number of bytes still to be transferred.
*/
int
com_outfull(VOID)
{
return(ThisBuffer->SerialIndex - ThisBuffer->SerialBuffer + NextBuffer->SerialIndex - NextBuffer->SerialBuffer);
}
/* carrier(VOID):
*
* Return current carrier status.
*/
int
carrier(VOID)
{
if(nocarrier)
return(1);
else
{
if(!ThisBuffer->IsBusy)
{
ThisBuffer->SerialRequest->IOSer.io_Command = SDCMD_QUERY;
DoIO(ThisBuffer->SerialRequest);
if(ThisBuffer->SerialRequest->io_Status & CIAF_COMCD)
return(0);
else
return(1);
}
else
{
NextBuffer->SerialRequest->IOSer.io_Command = SDCMD_QUERY;
DoIO(NextBuffer->SerialRequest);
if(NextBuffer->SerialRequest->io_Status & CIAF_COMCD)
return(0);
else
return(1);
}
}
}
/* com_flush(VOID):
*
* Make sure all pending data gets written.
*/
VOID
com_flush(VOID)
{
if(ThisBuffer->IsBusy)
{
WaitIO(ThisBuffer->SerialRequest);
ThisBuffer->IsBusy = FALSE;
ThisBuffer->SerialIndex = ThisBuffer->SerialBuffer;
}
if(NextBuffer->SerialIndex > NextBuffer->SerialBuffer)
{
NextBuffer->SerialRequest->IOSer.io_Command = CMD_WRITE;
NextBuffer->SerialRequest->IOSer.io_Data = NextBuffer->SerialBuffer;
NextBuffer->SerialRequest->IOSer.io_Length = NextBuffer->SerialIndex - NextBuffer->SerialBuffer;
DoIO(NextBuffer->SerialRequest);
NextBuffer->SerialIndex = NextBuffer->SerialBuffer;
}
}
/* com_putbyte(byte c):
*
* Transmit a single byte, queueing it if necessary.
*/
VOID
com_putbyte(byte c)
{
if(ThisBuffer->IsBusy)
{
if(NextBuffer->SerialIndex + 1 >= NextBuffer->SerialTop)
{
struct SerialBuffer *Swap = ThisBuffer;
WaitIO(ThisBuffer->SerialRequest);
ThisBuffer->IsBusy = FALSE;
ThisBuffer->SerialIndex = ThisBuffer->SerialBuffer;
ThisBuffer = NextBuffer;
NextBuffer = Swap;
ThisBuffer->IsBusy = TRUE;
ThisBuffer->SerialRequest->IOSer.io_Command = CMD_WRITE;
ThisBuffer->SerialRequest->IOSer.io_Data = ThisBuffer->SerialBuffer;
ThisBuffer->SerialRequest->IOSer.io_Length = ThisBuffer->SerialIndex - ThisBuffer->SerialBuffer;
ClrSignal(SIG_SERWRITE);
SendIO(ThisBuffer->SerialRequest);
}
*NextBuffer->SerialIndex++ = c;
}
else
{
if(ThisBuffer->SerialIndex + 1 < ThisBuffer->SerialTop)
{
*ThisBuffer->SerialIndex++ = c;
ThisBuffer->IsBusy = TRUE;
ThisBuffer->SerialRequest->IOSer.io_Command = CMD_WRITE;
ThisBuffer->SerialRequest->IOSer.io_Data = ThisBuffer->SerialBuffer;
ThisBuffer->SerialRequest->IOSer.io_Length = 1;
ClrSignal(SIG_SERWRITE);
SendIO(ThisBuffer->SerialRequest);
}
else
{
ThisBuffer->IsBusy = TRUE;
ThisBuffer->SerialRequest->IOSer.io_Command = CMD_WRITE;
ThisBuffer->SerialRequest->IOSer.io_Data = ThisBuffer->SerialBuffer;
ThisBuffer->SerialRequest->IOSer.io_Length = ThisBuffer->SerialIndex - ThisBuffer->SerialBuffer;
ClrSignal(SIG_SERWRITE);
SendIO(ThisBuffer->SerialRequest);
*NextBuffer->SerialIndex++ = c;
}
}
}
/* com_purge(VOID):
*
* Clear the read/write buffers.
*/
VOID
com_purge(VOID)
{
if(ThisBuffer->IsBusy)
{
if(!CheckIO(ThisBuffer->SerialRequest))
AbortIO(ThisBuffer->SerialRequest);
WaitIO(ThisBuffer->SerialRequest);
}
ThisBuffer->IsBusy = FALSE;
ThisBuffer->SerialIndex = ThisBuffer->SerialBuffer;
NextBuffer->IsBusy = FALSE;
NextBuffer->SerialIndex = NextBuffer->SerialBuffer;
if(ReadBuffer->IsBusy)
{
if(!CheckIO(ReadBuffer->SerialRequest))
AbortIO(ReadBuffer->SerialRequest);
WaitIO(ReadBuffer->SerialRequest);
}
ReadBuffer->IsBusy = FALSE;
ReadBuffer->SerialIndex = ReadBuffer->SerialBuffer;
ReadBuffer->SerialFilled = 0;
ThisBuffer->SerialRequest->IOSer.io_Command = CMD_CLEAR;
DoIO(ThisBuffer->SerialRequest);
}
/* com_dump(VOID):
*
* Wait for asynchronous write request to terminate.
*/
VOID
com_dump(VOID)
{
com_flush();
}
/* com_getbyte(VOID):
*
* Read a single byte from the serial line. If not available,
* return EOF.
*/
int
com_getbyte(VOID)
{
int Result;
if(ReadBuffer->SerialFilled <= 0)
{
if(ReadBuffer->IsBusy)
{
if(!CheckIO(ReadBuffer->SerialRequest))
return(EOF);
else
WaitIO(ReadBuffer->SerialRequest);
ReadBuffer->IsBusy = FALSE;
ReadBuffer->SerialFilled = ReadBuffer->SerialRequest->IOSer.io_Actual;
ReadBuffer->SerialIndex = ReadBuffer->SerialBuffer;
ReadBuffer->SerialRequest->IOSer.io_Command = SDCMD_QUERY;
DoIO(ReadBuffer->SerialRequest);
if(ReadBuffer->SerialRequest->IOSer.io_Actual)
{
LONG Size = ReadBuffer->SerialSize - ReadBuffer->SerialFilled;
if(Size > 0)
{
if(Size > ReadBuffer->SerialRequest->IOSer.io_Actual)
Size = ReadBuffer->SerialRequest->IOSer.io_Actual;
ReadBuffer->SerialRequest->IOSer.io_Command = CMD_READ;
ReadBuffer->SerialRequest->IOSer.io_Data = ReadBuffer->SerialBuffer + ReadBuffer->SerialFilled;
ReadBuffer->SerialRequest->IOSer.io_Length = Size;
DoIO(ReadBuffer->SerialRequest);
ReadBuffer->SerialFilled += ReadBuffer->SerialRequest->IOSer.io_Actual;
}
}
}
else
{
ReadBuffer->SerialRequest->IOSer.io_Command = SDCMD_QUERY;
DoIO(ReadBuffer->SerialRequest);
if(!ReadBuffer->SerialRequest->IOSer.io_Actual)
return(EOF);
else
{
ReadBuffer->SerialRequest->IOSer.io_Command = CMD_READ;
ReadBuffer->SerialRequest->IOSer.io_Data = ReadBuffer->SerialBuffer;
ReadBuffer->SerialRequest->IOSer.io_Length = MIN(ReadBuffer->SerialRequest->IOSer.io_Actual,ReadBuffer->SerialSize);
DoIO(ReadBuffer->SerialRequest);
if(!ReadBuffer->SerialRequest->IOSer.io_Actual)
return(EOF);
else
{
ReadBuffer->SerialFilled = ReadBuffer->SerialRequest->IOSer.io_Actual;
ReadBuffer->SerialIndex = ReadBuffer->SerialBuffer;
}
}
}
}
Result = *ReadBuffer->SerialIndex++;
ReadBuffer->SerialFilled--;
if(ReadBuffer->SerialFilled <= 0)
{
ReadBuffer->IsBusy = TRUE;
ReadBuffer->SerialIndex = ReadBuffer->SerialBuffer;
ReadBuffer->SerialRequest->IOSer.io_Command = CMD_READ;
ReadBuffer->SerialRequest->IOSer.io_Data = ReadBuffer->SerialBuffer;
ReadBuffer->SerialRequest->IOSer.io_Length = 1;
ClrSignal(SIG_SERREAD);
SendIO(ReadBuffer->SerialRequest);
}
return(Result);
}
/* setstamp(STRPTR Name,LONG Time):
*
* Set time/date of a file.
*/
VOID
setstamp(char *Name,long Time)
{
struct DateStamp Date;
ULONG Seconds;
DB(kprintf("setstamp |%s| %ld\n",Name,Time));
/* Translate it into an Amiga date. */
if(Time > GMT_Offset)
Seconds = Time - GMT_Offset;
else
Seconds = 0;
Date.ds_Days = Seconds / (24 * 60 * 60);
Date.ds_Minute = (Seconds % (24 * 60 * 60)) / 60;
Date.ds_Tick = (Seconds % 60) * TICKS_PER_SECOND;
SetFileDate(Name,&Date);
}
/* freespace(STRPTR DrivePath):
*
* Get free disk space for specified drive.
*/
long
freespace(char *DrivePath)
{
struct DevProc *DevProc;
struct DosList *DosList;
BOOL GoodDevice;
LONG Size;
if(!DrivePath)
DrivePath = "";
DB(kprintf("freespace |%s|\n",DrivePath));
DevProc = GetDeviceProc(DrivePath,NULL);
GoodDevice = FALSE;
Size = (LONG)((ULONG)~0 >> 2);
if(DosList = LockDosList(LDF_DEVICES | LDF_READ))
{
while(DosList = NextDosEntry(DosList,LDF_DEVICES))
{
if(DosList->dol_Task == DevProc->dvp_Port)
{
struct FileSysStartupMsg *FSSM = (struct FileSysStartupMsg *)BADDR(DosList->dol_misc.dol_handler.dol_Startup);
if(TypeOfMem(FSSM))
{
struct DosEnvec *DosEnvec = (struct DosEnvec *)BADDR(FSSM->fssm_Environ);
STRPTR Name = (STRPTR)BADDR(FSSM->fssm_Device);
if(TypeOfMem(DosEnvec) && TypeOfMem(Name))
{
if(Name[0] > 0 && !Name[(WORD)Name[0] + 1])
{
struct IOStdReq IORequest;
memset(&IORequest,0,sizeof(IORequest));
IORequest.io_Message.mn_Length = sizeof(IORequest);
if(!OpenDevice(Name + 1,FSSM->fssm_Unit,&IORequest,FSSM->fssm_Unit))
{
CloseDevice(&IORequest);
if(DosEnvec->de_TableSize > 0 && DosEnvec->de_LowCyl <= DosEnvec->de_HighCyl)
GoodDevice = TRUE;
}
}
}
}
}
}
UnLockDosList(LDF_DEVICES | LDF_READ);
}
FreeDeviceProc(DevProc);
if(GoodDevice)
{
struct InfoData *InfoData;
if(InfoData = (struct InfoData *)AllocVec(sizeof(struct InfoData),MEMF_ANY | MEMF_PUBLIC))
{
UBYTE NewName[MAX_FILENAME_LENGTH],*Index;
BPTR FileLock;
memcpy(NewName,DrivePath,sizeof(NewName) - 1);
NewName[sizeof(NewName) - 1] = 0;
Index = PathPart(NewName);
*Index = 0;
FileLock = Lock(NewName,ACCESS_READ);
if(FileLock)
{
if(Info(FileLock,InfoData))
Size = InfoData->id_BytesPerBlock * (InfoData->id_NumBlocks - InfoData->id_NumBlocksUsed);
UnLock(FileLock);
}
FreeVec(InfoData);
}
}
return(Size);
}
/* ffirst(char *FileSpec):
*
* Return name of first file matching the given specs.
*/
char *
ffirst(char *filespec)
{
AnchorUsed = TRUE;
DB(kprintf("ffirst |%s|\n",filespec));
if(MatchFirst(filespec,Anchor))
return(NULL);
else
return((char *)Anchor->ap_Buf);
}
/* fnext(VOID):
*
* Return name of next file matching the given specs.
*/
char *
fnext(VOID)
{
AnchorUsed = TRUE;
DB(kprintf("fnext\n"));
if(MatchNext(Anchor))
return(NULL);
else
return((char *)Anchor->ap_Buf);
}
/* time(time_t *timeptr):
*
* Get the current time.
*/
time_t
time(time_t *timeptr)
{
struct timeval Now;
time_t CurrentTime;
DB(kprintf("time 0x%08lx\n",timeptr));
/* If the timer is already available,
* just read the time. Otherwise, open what
* we need to tell the time.
*/
if(TimerBase)
GetSysTime(&Now);
else
UpdateTime(&Now);
/* Determine the current time, taking the time
* zone into account.
*/
CurrentTime = (time_t)(Now.tv_secs + GMT_Offset);
if(timeptr)
*timeptr = CurrentTime;
return(CurrentTime);
}
/* localtime(const time_t *t):
*
* Convert UTC into local time.
*/
struct tm *
localtime(const time_t *t)
{
STATIC struct tm Time;
ULONG Seconds,
Delta;
struct ClockData ClockData;
BOOL CloseIt = FALSE;
DB(kprintf("localtime 0x%08lx\n",t));
/* We need utility.library for the date conversion. */
if(!UtilityBase)
{
if(UtilityBase = OpenLibrary("utility.library",37))
CloseIt = TRUE;
}
/* Any luck? */
if(!UtilityBase)
{
memset(&Time,0,sizeof(struct tm));
return(&Time);
}
/* Update the time data. */
if(!TimerBase)
UpdateTime(NULL);
/* Add the offset. */
if(*t < GMT_Offset)
Seconds = 0;
else
Seconds = (ULONG)*t - GMT_Offset;
/* Convert the seconds into time data. */
Amiga2Date(Seconds,&ClockData);
/* Convert the time data. */
Time.tm_sec = ClockData.sec;
Time.tm_min = ClockData.min;
Time.tm_hour = ClockData.hour;
Time.tm_mday = ClockData.mday;
Time.tm_mon = ClockData.month - 1;
Time.tm_year = ClockData.year - 1900;
Time.tm_wday = ClockData.wday;
/* No daylight savings time info is provided. */
Time.tm_isdst = 0;
/* We will need to fill in the yday entry. */
ClockData.mday = 1;
ClockData.month = 1;
Delta = Date2Amiga(&ClockData);
Time.tm_yday = (Seconds - Delta) / (24 * 60 * 60) + 1;
/* Clean up if necessary. */
if(CloseIt)
{
CloseLibrary(UtilityBase);
UtilityBase = NULL;
}
return(&Time);
}
/* stat(const char *file,struct stat *st):
*
* Get information on a file.
*/
int
stat(const char *file,struct stat *st)
{
BPTR FileLock;
D_S(struct FileInfoBlock,FileInfo);
DB(kprintf("stat |%s| 0%08lx\n",file,st));
/* Try to get a lock on the file. */
if(FileLock = Lock((STRPTR)file,ACCESS_READ))
{
STATIC char Volume[MAX_FILENAME_LENGTH],Comment[80];
D_S(struct InfoData,InfoData);
/* Get information on file and filing system. */
if(Examine(FileLock,FileInfo) && Info(FileLock,InfoData))
{
unsigned short mode = 0;
/* Try to get the name of the volume. */
if(!NameFromLock(FileLock,Volume,sizeof(Volume)))
Volume[0] = 0;
else
{
WORD i;
/* Chop off everything after the colon. */
for(i = 0 ; i < sizeof(Volume) ; i++)
{
if(Volume[i] == ':')
{
Volume[i + 1] = 0;
break;
}
}
}
UnLock(FileLock);
/* Build the protection bits. */
if(!(FileInfo->fib_Protection & FIBF_EXECUTE))
mode |= S_IEXECUTE;
if(!(FileInfo->fib_Protection & FIBF_DELETE))
mode |= S_IDELETE;
if(!(FileInfo->fib_Protection & FIBF_READ))
mode |= S_IREAD;
if(!(FileInfo->fib_Protection & FIBF_WRITE))
mode |= S_IWRITE;
if(!(FileInfo->fib_Protection & FIBF_ARCHIVE))
mode |= S_IARCHIVE;
if(FileInfo->fib_Protection & FIBF_PURE)
mode |= S_IPURE;
if(FileInfo->fib_Protection & FIBF_SCRIPT)
mode |= S_ISCRIPT;
/* Keep the comment. */
CopyMem(FileInfo->fib_Comment,Comment,79);
Comment[79] = 0;
/* Fix the time if necessary. */
if(!TimerBase)
UpdateTime(NULL);
/* Fill in the data. */
st->st_mode = mode;
st->st_ino = FileInfo->fib_DiskKey;
st->st_dev = InfoData->id_DiskType;
st->st_rdev = Volume;
st->st_nlink = FileInfo->fib_DirEntryType == ST_SOFTLINK || FileInfo->fib_DirEntryType == ST_LINKDIR || FileInfo->fib_DirEntryType == ST_LINKFILE;
st->st_uid = FileInfo->fib_OwnerUID;
st->st_gid = FileInfo->fib_OwnerGID;
st->st_size = FileInfo->fib_Size;
st->st_atime = GMT_Offset + (FileInfo->fib_Date.ds_Days * 24 * 60 + FileInfo->fib_Date.ds_Minute) * 60 + (FileInfo->fib_Date.ds_Tick / TICKS_PER_SECOND);
st->st_mtime = st->st_atime;
st->st_ctime = st->st_atime;
st->st_type = FileInfo->fib_DirEntryType;
st->st_comment = Comment;
/* Success. */
return(0);
}
UnLock(FileLock);
}
/* What else should I choose? */
errno = _OSERR = EIO;
return(-1);
}